using System;
using System.Collections;
using System.Windows.Forms;

namespace Framework
{
    ///<summary>
    ///</summary>
    public abstract class DefaultFolderObject : IFolderObject
    {
        private byte[][] _rootPath;
        private byte[][] _pathData;

        #region IFolderObject Members

        ///<summary>
        ///</summary>
        public virtual FolderAttributes Attributes
        {
            get { return FolderAttributes.None; }
        }

        ///<summary>
        ///</summary>
        public virtual ColumnCollection Columns
        {
            get { return new ColumnCollection(); }
        }

        ///<summary>
        ///</summary>
        ///<param name="column"></param>
        ///<param name="object"></param>
        ///<returns></returns>
        public virtual int CompareTo(Column column, IFolderObject @object)
        {
            // get the values for this item and the other item in the
            // specified column

            object columnValue = GetColumnValue(column);
            object objectValue = @object.GetColumnValue(column);

            if (column != null && column.Comparer != null)
            {
                // the column provides a comparer
                return column.Comparer.Compare(columnValue, objectValue);
            }
            if (columnValue == null && objectValue != null)
            {
                return 1; // sort empty column values to the bottom
            }
            if (objectValue == null && columnValue != null)
            {
                return -1; // sort empty column values to the bottom
            }
            // ReSharper disable ConditionIsAlwaysTrueOrFalse
            return columnValue == null && objectValue == null ||
                   !(columnValue is IComparable && objectValue is IComparable)
                       ? this.GetDisplayName(NameOptions.Normal).CompareTo(@object.GetDisplayName(NameOptions.Normal))
                       : ((IComparable)columnValue).CompareTo(objectValue);
            // ReSharper restore ConditionIsAlwaysTrueOrFalse
        }

        ///<summary>
        ///</summary>
        public virtual DataObject DataObject
        {
            get { return null; }
        }

        ///<summary>
        ///</summary>
        ///<param name="column"></param>
        ///<returns></returns>
        public virtual object GetColumnValue(Column column)
        {
            return null;
        }

        ///<summary>
        ///</summary>
        ///<param name="opts"></param>
        ///<returns></returns>
        public abstract string GetDisplayName(NameOptions opts);

        ///<summary>
        ///</summary>
        ///<param name="open"></param>
        ///<returns></returns>
        public virtual ShellIcon GetIcon(bool open)
        {
            return null;
        }

        ///<summary>
        ///</summary>
        ///<param name="owner"></param>
        ///<returns></returns>
        public virtual IEnumerable GetItems(IWin32Window owner)
        {
            return null;
        }

        ///<summary>
        ///</summary>
        ///<param name="children"></param>
        ///<returns></returns>
        public virtual ShellMenuItem[] GetMenuItems(IFolderObject[] children)
        {
            return null;
        }

        ///<summary>
        ///</summary>
        public virtual ShellMenuItem[] MenuItems
        {
            get { return null; }
        }

        ///<summary>
        ///</summary>
        ///<exception cref="InvalidOperationException"></exception>
        public virtual byte[][] PathData
        {
            get
            {
                if (this._rootPath == null)
                {
                    throw new InvalidOperationException("Path not initialized with SetPath");
                }
                if (this._pathData == null)
                {
                    this._pathData = new byte[this._rootPath.Length + 1][];
                    Array.Copy(this._rootPath, 0, this._pathData, 0, this._rootPath.Length);
                    this._pathData[this._pathData.Length - 1] = this.Persist();
                }

                return (byte[][])this._pathData.Clone();
            }
        }

        ///<summary>
        ///</summary>
        ///<returns></returns>
        public abstract byte[] Persist();

        ///<summary>
        ///</summary>
        ///<param name="data"></param>
        ///<returns></returns>
        public abstract IFolderObject Restore(byte[] data);

        ///<summary>
        ///</summary>
        ///<exception cref="NotSupportedException"></exception>
        public virtual string RemoteComputer
        {
            set { throw new NotSupportedException(); }
        }

        ///<summary>
        ///</summary>
        ///<param name="owner"></param>
        ///<param name="name"></param>
        ///<param name="opts"></param>
        ///<exception cref="NotSupportedException"></exception>
        public virtual void SetName(IWin32Window owner, string name, NameOptions opts)
        {
            throw new NotSupportedException();
        }

        ///<summary>
        ///</summary>
        ///<param name="data"></param>
        ///<exception cref="InvalidOperationException"></exception>
        public virtual void SetPath(byte[][] data)
        {
            if (this._rootPath != null)
            {
                throw new InvalidOperationException("Path already initialized");
            }

            this._rootPath = (byte[][])data.Clone();
        }

        ///<summary>
        ///</summary>
        ///<param name="data"></param>
        ///<exception cref="InvalidOperationException"></exception>
        public virtual void SetFullPath(byte[][] data)
        {
            if (this._rootPath != null)
            {
                throw new InvalidOperationException("Path already initialized");
            }

            this._rootPath = new byte[data.Length - 1][];
            Array.Copy(data, 0, this._rootPath, 0, data.Length - 1);

            this._pathData = (byte[][])data.Clone();
        }

        #endregion

        protected virtual ExploreMenuItem CreateExploreMenuItem()
        {
            return CreateExploreMenuItem("Explore", "Explore", ExploreMenuItem.ExploreVerb);
        }

        protected virtual ExploreMenuItem CreateOpenMenuItem()
        {
            return CreateExploreMenuItem("Open", "Open", ExploreMenuItem.OpenVerb);
        }

        protected virtual ExploreMenuItem CreateExploreMenuItem(string text, string helpText, string verb)
        {
            return new ExploreMenuItem(PathData, text, helpText, verb);
        }

        protected virtual byte[][] RootPathData
        {
            get { return (byte[][])this._rootPath.Clone(); }
        }
    } ;
}
